package com.simpou.commons.web.filter;


/**
 * Jersey filter responsável por habilitar requests cross origin.
 *
 * @author Jonas Pereira
 * @since 2013-01-10
 */
public abstract class AbstractCORSFilter {
    /**
     * @param header Filtra a resposta da requisição adicionando ao seu
     * cabeçalho os parâmetros CORS de forma a permitir todas requisições.
     * Autenticação também é permitida.
     * @param method Método HTTP. Somente requisições OPTIONS serão filtradas.
     */
    protected void fillHeader(final Header header, final String method) {
        // por padrão segurança será permitida pelo CORS
        header.addResponseHeader("Access-Control-Allow-Credentials", "true");

        // alguns métodos não geram OPTIONS antes
        doEcho(header, "Origin", "Access-Control-Allow-Origin");

        if (method.equals("OPTIONS")) {
            // ecoa as solicitções do request para o response para perimitir tudo
            // que foi solicitado.
            doEcho(header, "Access-Control-Request-Headers",
                "Access-Control-Allow-Headers");
            doEcho(header, "Access-Control-Request-Method",
                "Access-Control-Allow-Methods");

            // configurações que funcioname na maioria dos casos
            //            header.addResponseHeader("Access-Control-Allow-Origin",
            //                RestPropertiesHelper.SEC_ORIGINS_ALLOWED);
            //            headeraddHeader("Access-Control-Allow-Methods",
            //                "GET, POST, PUT, DELETE");
            //            headeraddHeader("Access-Control-Allow-Headers",
            //                "content-type, accept, origin, authorization, x-requested-with, x-requested-by");
        }
    }

    /**
     * Ecoa as opções CORS da requisição para a resposta, de forma a permitir
     * todas.
     *
     * @param header Objeto header.
     * @param source Nome do header da requisição.
     * @param target Nomde do header da resposta.
     */
    private void doEcho(final Header header, final String source,
        final String target) {
        final String sourceValue = header.getRequestHeader(source);
        header.addResponseHeader(target, sourceValue);
    }

    /**
     * O request e o response depende da classe que implementa e do contexto.
     * Interface para abstrair estas diferenças e aplicar os headers
     * independentemente.
     */
    protected interface Header {
        /**
         * Adiciona um registro ao cabeçalho da reasposta.
         *
         * @param key Chave do header.
         * @param value Valor do header.
         */
        void addResponseHeader(final String key, final String value);

        /**
         * Consulta um valor do cabeçalho da requisição.
         *
         * @param key Chave do header.
         * @return Valor do header.
         */
        String getRequestHeader(final String key);
    }
}
